package admin

import (
	"fmt"
	"geekai/api/dto/common"
	"geekai/api/dto/request"
	"geekai/api/dto/response"
	"geekai/api/handler"
	"geekai/core"
	"geekai/core/types"
	"geekai/model"
	"geekai/service"
	"geekai/service/oss"
	"geekai/utils"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type ImageHandler struct {
	handler.BaseHandler
	userService *service.UserService
	uploader    *oss.UploaderManager
}

func NewImageHandler(app *core.AppServer, db *gorm.DB, userService *service.UserService, manager *oss.UploaderManager) *ImageHandler {
	return &ImageHandler{
		BaseHandler: handler.BaseHandler{App: app, DB: db},
		userService: userService,
		uploader:    manager,
	}
}

// MjList godoc
// @Summary      Midjourney 任务列表
// @Description  Midjourney 任务列表
// @Tags         后台管理-绘图管理
// @Accept       json
// @Produce      json
// @Param        req   body     request.ImageQueryReq  true  "查询参数"
// @Success      200  {object}  types.BizVo{data=response.Page}
// @Router       /api/admin/image/list/mj [post]
// @Security AdminApiKeyAuth
func (h *ImageHandler) MjList(c *gin.Context) {
	var data request.ImageQueryReq
	if err := c.ShouldBindJSON(&data); err != nil {
		utils.ERROR(c, types.InvalidArgs)
		return
	}

	session := h.DB.Session(&gorm.Session{})
	if data.Username != "" {
		var user model.User
		// 查询用户信息
		err := h.DB.Where("username", data.Username).First(&user).Error
		if err == nil {
			session = session.Where("user_id", user.Id)
		}
	}
	if data.Prompt != "" {
		session = session.Where("prompt like ?", fmt.Sprintf("%s%s%s", "%", data.Prompt, "%"))
	}
	if len(data.CreatedAt) == 2 {
		session = session.Where("created_at >= ? and created_at <= ?", data.CreatedAt[0], data.CreatedAt[1])
	}
	var total int64
	// 查询数据总数
	session.Model(&model.MidJourneyJob{}).Count(&total)
	var list []model.MidJourneyJob
	var items = make([]common.MidJourneyJob, 0)
	offset := (data.Page - 1) * data.PageSize
	err := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&list).Error
	if err == nil {
		// 填充数据
		for _, item := range list {
			var job common.MidJourneyJob
			err = utils.CopyObject(item, &job)
			if err != nil {
				log.Errorf("拷贝数据出错：%v", err.Error())
				continue
			}
			job.CreatedAt = item.CreatedAt.Unix()
			items = append(items, job)
		}
	}
	utils.SUCCESS(c, response.NewPage(total, data.Page, data.PageSize, items))
}

// SdList godoc
// @Summary      Stable Diffusion 任务列表
// @Description  Stable Diffusion 任务列表
// @Tags         后台管理-绘图管理
// @Accept       json
// @Produce      json
// @Param        req   body     request.ImageQueryReq  true  "查询参数"
// @Success      200  {object}  types.BizVo{data=response.Page}
// @Router       /api/admin/image/list/sd [post]
// @Security AdminApiKeyAuth
func (h *ImageHandler) SdList(c *gin.Context) {
	var data request.ImageQueryReq
	if err := c.ShouldBindJSON(&data); err != nil {
		utils.ERROR(c, types.InvalidArgs)
		return
	}
	session := h.DB.Session(&gorm.Session{})
	if data.Username != "" {
		var user model.User
		err := h.DB.Where("username", data.Username).First(&user).Error
		if err == nil {
			session = session.Where("user_id", user.Id)
		}
	}
	if data.Prompt != "" {
		session = session.Where("prompt like ?", fmt.Sprintf("%s%s%s", "%", data.Prompt, "%"))
	}
	if len(data.CreatedAt) == 2 {
		session = session.Where("created_at >= ? and created_at <= ?", data.CreatedAt[0], data.CreatedAt[1])
	}

	var total int64
	session.Model(&model.SdJob{}).Count(&total)
	var list []model.SdJob
	var items = make([]common.SdJob, 0)
	offset := (data.Page - 1) * data.PageSize
	err := session.Order("id desc").Offset(offset).Limit(data.PageSize).Find(&list).Error
	if err == nil {
		// 填充数据
		for _, item := range list {
			var job common.SdJob
			err = utils.CopyObject(item, &job)
			if err != nil {
				log.Errorf("拷贝数据出错：%v", err.Error())
				continue
			}
			job.CreatedAt = item.CreatedAt.Unix()
			items = append(items, job)
		}
	}
	utils.SUCCESS(c, response.NewPage(total, data.Page, data.PageSize, items))
}

// DallList godoc
// @Summary      DALL-E 任务列表
// @Description  DALL-E 任务列表
// @Tags         后台管理-绘图管理
// @Accept       json
// @Produce      json
// @Param        req   body     request.ImageQueryReq  true  "查询参数"
// @Success      200  {object}  types.BizVo{data=response.Page}
// @Router       /api/admin/image/list/dall [post]
// @Security AdminApiKeyAuth
func (h *ImageHandler) DallList(c *gin.Context) {
	var data request.ImageQueryReq
	if err := c.ShouldBindJSON(&data); err != nil {
		utils.ERROR(c, types.InvalidArgs)
		return
	}
	session := h.DB.Session(&gorm.Session{})
	if data.Username != "" {
		var user model.User
		err := h.DB.Where("username", data.Username).First(&user).Error
		if err == nil {
			session = session.Where("user_id", user.Id)
		}
	}
	if data.Prompt != "" {
		session = session.Where("prompt like ?", fmt.Sprintf("%s%s%s", "%", data.Prompt, "%"))
	}
	if len(data.CreatedAt) == 2 {
		session = session.Where("created_at >= ? and created_at <= ?", data.CreatedAt[0], data.CreatedAt[1])
	}

	var total int64
	session.Model(&model.DallJob{}).Count(&total)
	var list []model.DallJob
	var items = make([]common.DallJob, 0)
	offset := (data.Page - 1) * data.PageSize
	err := session.Order("id desc").Offset(offset).Limit(data.PageSize).Find(&list).Error
	if err == nil {
		// 填充数据
		for _, item := range list {
			var job common.DallJob
			err = utils.CopyObject(item, &job)
			if err != nil {
				log.Errorf("数据拷贝失败：%v", err)
				continue
			}
			job.CreatedAt = item.CreatedAt.Unix()
			items = append(items, job)
		}
	}
	utils.SUCCESS(c, response.NewPage(total, data.Page, data.PageSize, items))
}

// Remove godoc
// @Summary      删除任务列表
// @Description  删除任务列表
// @Tags         后台管理-绘图管理
// @Accept       json
// @Produce      json
// @Param        id   query     int  true  "任务Id"
// @Param        tab  query     string  true  "任务类型"
// @Success      200  {object}  types.BizVo{}
// @Router       /api/admin/image/remove [get]
// @Security AdminApiKeyAuth
func (h *ImageHandler) Remove(c *gin.Context) {
	id := h.GetInt(c, "id", 0)
	tab := h.GetTrim(c, "tab")
	// 开启事务
	tx := h.DB.Begin()

	var md, remark, imgURL string
	var power, userId, progress int

	switch tab {
	case "mj":
		var job model.MidJourneyJob
		// 查询数据
		if err := h.DB.Where("id", id).First(&job).Error; err != nil {
			utils.ERROR(c, "要删除的记录不存在")
			return
		}
		// 删除记录
		tx.Delete(&job)
		md = "mid-journey"
		power = job.Power
		userId = int(job.UserId)
		remark = fmt.Sprintf("任务失败，退回算力。任务ID：%d，Err：%s", job.Id, job.ErrMsg)
		progress = job.Progress
		imgURL = job.ImgURL
		break
	case "sd":
		var job model.SdJob
		// 查询数据
		if err := h.DB.Where("id", id).First(&job).Error; err != nil {
			utils.ERROR(c, "要删除的记录不存在")
			return
		}
		// 删除记录
		tx.Delete(&job)
		md = "stable-diffusion"
		power = job.Power
		userId = int(job.UserId)
		remark = fmt.Sprintf("任务失败，退回算力。任务ID：%d，Err：%s", job.Id, job.ErrMsg)
		progress = job.Progress
		imgURL = job.ImgURL
		break
	case "dall":
		var job model.DallJob
		// 查询数据
		if err := h.DB.Where("id", id).First(&job).Error; err != nil {
			utils.ERROR(c, "要删除的记录不存在")
			return
		}
		// 删除记录
		tx.Delete(&job)
		md = "dall-e-3"
		power = job.Power
		userId = int(job.UserId)
		remark = fmt.Sprintf("任务失败，退回算力。任务ID：%d，Err：%s", job.Id, job.ErrMsg)
		progress = job.Progress
		imgURL = job.ImgURL
		break
	default:
		utils.ERROR(c, types.InvalidArgs)
		return
	}

	// 判断任务进度不等于100
	if progress != 100 {
		// 退回用户算力
		err := h.userService.IncreasePower(userId, power, model.PowerLog{
			Type:   types.PowerRefund,
			Model:  md,
			Remark: remark,
		})
		if err != nil {
			// 事务回滚
			tx.Rollback()
			utils.ERROR(c, "操作数据库失败："+err.Error())
			return
		}
	}
	// 提交事务
	tx.Commit()
	// 删除图片
	err := h.uploader.GetUploadHandler().Delete(imgURL)
	if err != nil {
		log.Errorf("删除绘画任务时，删除图片出错：%v", err.Error())
	}
	utils.SUCCESS(c)
}
